#pragma once

namespace G3D
{
    class Vector3;
    class Matrix3;
    class AABox;
    class Ray;
}
class GameObjectModel;

/**
 * @brief
 *
 */
class DynamicMapTree
{
public:
    /**
     * @brief
     *
     */
    DynamicMapTree();
    /**
     * @brief
     *
     */
    ~DynamicMapTree();

    /**
     * @brief
     *
     * @param x1
     * @param y1
     * @param z1
     * @param x2
     * @param y2
     * @param z2
     * @return bool
     */
    bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const;
    /**
     * @brief
     *
     * @param ray
     * @param endPos
     * @param maxDist
     * @return bool
     */
    bool getIntersectionTime(const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const;
    /**
     * @brief
     *
     * @param pPos1
     * @param pPos2
     * @param pResultHitPos
     * @param pModifyDist
     * @return bool
     */
    bool getObjectHitPos(const G3D::Vector3& pPos1, const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
    /**
     * @brief
     *
     * @param x1
     * @param y1
     * @param z1
     * @param x2
     * @param y2
     * @param z2
     * @param rx
     * @param ry
     * @param rz
     * @param pModifyDist
     * @return bool
     */
    bool getObjectHitPos(float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float pModifyDist) const;
    /**
     * @brief
     *
     * @param x
     * @param y
     * @param z
     * @param maxSearchDist
     * @return float
     */
    float getHeight(float x, float y, float z, float maxSearchDist) const;

    /**
     * @brief
     *
     * @param
     */
    void insert(const GameObjectModel&);
    /**
     * @brief
     *
     * @param
     */
    void remove(const GameObjectModel&);
    /**
     * @brief
     *
     * @param
     * @return bool
     */
    bool contains(const GameObjectModel&) const;
    /**
     * @brief
     *
     * @return int
     */
    int size() const;

    /**
     * @brief
     *
     */
    void balance();
    /**
     * @brief
     *
     * @param diff
     */
    void update(unsigned int diff);
private:
    struct DynTreeImpl& impl; /**< TODO */
};